﻿using System;
using UnityEngine;
using UnityEngine.Events;
using Object = UnityEngine.Object;

namespace Zero.Dialogue
{
    [Serializable]
    public class OnTalkStartEvent : UnityEvent
    {
    }

    [Serializable]
    public class OnTalkCompleteEvent : UnityEvent
    {
    }

    [RequireComponent(typeof(BoxCollider2D))]
    public class NPCTalk : MonoBehaviour
    {
        [Header("交互提示")]
        [Tooltip("交互提示的位置偏移"),]
        public Vector3 talkTipOffset = Vector2.up;

        [Header("气泡消息")]
        [Tooltip("显示的消息"), TextArea]
        public string message;
        [Tooltip("气泡持续时间(单位:秒 特殊值:-1=无限 0=默认)")]
        public float duration = 0f;
        [Tooltip("是否只对话一次")]
        public bool isOnce = false;

        [Header("事件")]
        [Tooltip("开始对话时事件")]
        public OnTalkStartEvent onTalkStart;
        [Tooltip("完成对话时事件")]
        public OnTalkCompleteEvent onTalkComplete;

        /// <summary>
        /// 对话的目标
        /// </summary>
        public BubbleCharacter TalkTarget { get; private set; }
        private PlayerMovement _targetMovement;

        private BubbleCharacter _owner; // 绑定的角色

        private bool _isCanTalk = false; // 是否可对话
        private bool _isTalking = false; // 是否对话中

        private void OnEnable()
        {
            if (_owner == null)
            {
                _owner = GetComponent<BubbleCharacter>();
                if (_owner == null) _owner = GetComponentInParent<BubbleCharacter>();
            }

            // 注册对话气泡事件
            DialogueSystem.Instance.RegisterOnBubbleStart(_owner, OnBubbleStart);
            DialogueSystem.Instance.RegisterOnBubbleComplete(_owner, OnBubbleComplete);
        }

        private void OnDisable()
        {
            TalkTarget = null;

            // 取消注册对话气泡事件
            DialogueSystem.Instance.UnregisterOnBubbleStart(_owner, OnBubbleStart);
            DialogueSystem.Instance.UnregisterOnBubbleComplete(_owner, OnBubbleComplete);

            onTalkStart.RemoveAllListeners();
            onTalkComplete.RemoveAllListeners();
        }

        /// <summary>
        /// 对话气泡开始事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnBubbleStart(object sender, EventArgs e)
        {
            _isTalking = true;

            // 聊天开始时, 隐藏交互提示
            DialogueSystem.Instance.HideTalkTip();

            onTalkStart?.Invoke();
        }

        /// <summary>
        /// 对话气泡完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnBubbleComplete(object sender, EventArgs e)
        {
            _isTalking = false;

            // 存在对话奖励
            GetComponent<ITalkReward>()?.ReceiveReward(TalkTarget);

            // 如果只使用一次, 就销毁当前对象
            if (isOnce) Destroy(gameObject);
            else
            {
                // 聊天完成时, 显示交互提示
                if (_isCanTalk) DialogueSystem.Instance.ShowTalkTip(transform.position + talkTipOffset);
            }

            onTalkComplete?.Invoke();
        }


        private void Update()
        {
            if (_isCanTalk && !_isTalking)
            {
                if (Input.GetKeyDown(KeyCode.E))
                {
                    if (duration == 0f) _owner.ShowBubbleCustom(message);
                    else _owner.ShowBubbleCustom(message, duration);

                    // 设置玩家面向
                    if (_targetMovement != null)
                        _targetMovement.SetDirection(transform.position.x >= _targetMovement.transform.position.x);
                }
            }
        }

        private void OnTriggerEnter2D(Collider2D other)
        {
            if (other.CompareTag("Player"))
            {
                _isCanTalk = true;
                TalkTarget = other.GetComponent<BubbleCharacter>();
                if (TalkTarget == null)
                {
                    TalkTarget = other.GetComponentInChildren<BubbleCharacter>();
                    _targetMovement = other.GetComponent<PlayerMovement>();
                }

                // 不在对话中则显示交互提示
                if (!_isTalking) DialogueSystem.Instance.ShowTalkTip(transform.position + talkTipOffset);
            }
        }

        private void OnTriggerExit2D(Collider2D other)
        {
            if (other.CompareTag("Player"))
            {
                _isCanTalk = false;
                DialogueSystem.Instance.HideTalkTip();
            }
        }
    }
}